﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using ICSharpCode.SharpZipLib.Zip;

namespace LiveWriterBackupWPF
{
	public partial class canBackupControl
	{
        string _tempFolder = string.Format(@"{0}SJL\", System.IO.Path.GetTempPath());
        string _fileName = "";
        private bool _isRestore = false;
        private bool _isFinished = false;
        BackgroundWorker _doBackup;
        BackgroundWorker _doRestore;
        
		public canBackupControl()
		{
			this.InitializeComponent();
            _doRestore = GetRestoreWorker();
            _doBackup = GetBackupWorker();
		}

        internal frmMain MainForm { get; set; }

        public void StartBackup(WLBSettings settings, string filename)
        {
            _fileName = filename;
            _doBackup.RunWorkerAsync(settings);
        }

        public void StartRestore(string filename)
        {
            btnCancel.IsEnabled = false;
            _fileName = filename;
            _doRestore.RunWorkerAsync();
        }

        #region Restore Thread Methods
        private BackgroundWorker GetRestoreWorker()
        {
            BackgroundWorker result = new BackgroundWorker();
            result.WorkerReportsProgress = true;
            result.WorkerSupportsCancellation = false;
            result.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_doRestore_RunWorkerCompleted);
            result.ProgressChanged += new ProgressChangedEventHandler(_doRestore_ProgressChanged);
            result.DoWork += new DoWorkEventHandler(_doRestore_DoWork);
            return result;
        }
        
        void _doRestore_DoWork(object sender, DoWorkEventArgs e)
        {
            RestoreMethods rMethods = new RestoreMethods();

            WLBDebug.WriteToFile("Restore of \"" + _fileName + "\" started.");
            _doRestore.ReportProgress(12, "Loading backup...");
            ZipUtil.UnZipFiles(_fileName, _tempFolder, "", false);

            if (File.Exists(_tempFolder + "Settings.xml"))
            {

                WLBDebug.WriteToFile("Loading backup settings.");
                _doRestore.ReportProgress(24, "Loading backup settings...");
                Xml2Reg.Import(_tempFolder + "Settings.xml");
                WLBSettings settings = new WLBSettings();
                settings.GrabSettings(true);

                if (settings.Settings)
                {
                    WLBDebug.WriteToFile("Deleting current settings.");
                    DeleteSettings();
                    WLBDebug.WriteToFile("Restoring blog settings.");
                    _doRestore.ReportProgress(36, "Restoring blog settings...");
                    rMethods.RestoreBlogSettings();
                    WLBDebug.WriteToFile("Finished restoring blog settings.");
                }
                if (settings.IncludeBlogTemplates)
                {
                    WLBDebug.WriteToFile("Restoring blog templates.");
                    _doRestore.ReportProgress(48, "Restoring blog templates...");
                    rMethods.RestoreBlogTemplates();
                    WLBDebug.WriteToFile("Finished restoring blog templates.");
                }
                if (settings.IncludeLinkGlossary)
                {
                    WLBDebug.WriteToFile("Restoring link glossary.");
                    _doRestore.ReportProgress(60, "Restoring link glossary...");
                    rMethods.RestoreLinkGlossary();
                    WLBDebug.WriteToFile("Finished restoring link glossary.");
                }
                if (settings.Plugins)
                {
                    WLBDebug.WriteToFile("Restoring plugins.");
                    _doRestore.ReportProgress(72, "Restoring Plugins...");
                    rMethods.RestorePlugins();
                    WLBDebug.WriteToFile("Finished restoring plugins.");
                }
                if (settings.RecentPosts)
                {
                    WLBDebug.WriteToFile("Restoring recent posts.");
                    _doRestore.ReportProgress(84, "Restoring recent posts...");
                    rMethods.RestoreRecentPosts();
                    WLBDebug.WriteToFile("Finished restoring recent posts.");
                }
                if (settings.Drafts)
                {
                    WLBDebug.WriteToFile("Restoring drafts.");
                    _doRestore.ReportProgress(99, "Restoring drafts...");
                    rMethods.RestoreDrafts();
                    WLBDebug.WriteToFile("Finished restoring drafts.");
                }
            } // End check to see if Settings.xml exits
            else // Doesn't exists, means it's an old backup
            {
                LegacyRestore();
            }
        }

        // Work Item #2191 http://wlwbackup.codeplex.com/WorkItem/View.aspx?WorkItemId=2191
        private void DeleteSettings()
        {
            string regKey = @"Software\Microsoft\Windows Live\Writer";
            RegistryKey key = Registry.CurrentUser.OpenSubKey(regKey);
            if (key != null)
            {
                key.DeleteSubKeyTree(regKey);
                WLBDebug.WriteToFile("Settings deleted successfully, continuing restore.");
                key.Close();
            }
        }

        private void LegacyRestore()
        {
            LiveWriterBackup.BackupRestore backupRestore = new LiveWriterBackup.BackupRestore();
            WLBDebug.WriteToFile("Restoring your legacy backup.");
            _doRestore.ReportProgress(50, "Restoring your legacy backup...");
            backupRestore.doRestore(_tempFolder);
            WLBDebug.WriteToFile("Finished restoring legacy backup.");
            _doRestore.ReportProgress(100, "Finished restoring legacy backup.");
        }

        void _doRestore_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            string message = (string)e.UserState;
            prgBackupProgress.Value = (double)e.ProgressPercentage;
            txtbProgressUpdate.Text = message;
        }

        void _doRestore_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                WLBDebug.WriteToFile(e.Error.Message);
                WLBDebug.WriteToFile(e.Error.ToString());
            }
            else
            {
                WLBDebug.WriteToFile("Restore was successful.");
            }
            prgBackupProgress.Value = 100;
            txtbProgressUpdate.Text = "Restore completed.";
            btnCancel.Content = "OK";
            btnCancel.ToolTip = "Click to close"; // Work Item #1734 http://www.codeplex.com/WLWBackup/WorkItem/View.aspx?WorkItemId=1734
            btnCancel.IsEnabled = true;
            _isRestore = true;
        }
        #endregion

        private void BackupRestoreFinished()
        {
            _isRestore = false;
            btnCancel.IsEnabled = true;
            btnCancel.Content = "Cancel";
            btnCancel.ToolTip = "Cancel the backup"; 
            Storyboard backupDown = (Storyboard)MainForm.Resources["BackupDown"];
            backupDown.Begin();
        }

        #region Backup Thread Methods
        private BackgroundWorker GetBackupWorker()
        {
            BackgroundWorker result = new BackgroundWorker();
            result.WorkerReportsProgress = true;
            result.WorkerSupportsCancellation = true;
            result.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_doBackup_RunWorkerCompleted);
            result.ProgressChanged += new ProgressChangedEventHandler(_doBackup_ProgressChanged);
            result.DoWork += new DoWorkEventHandler(_doBackup_DoWork);
            return result;
        }

        void _doBackup_DoWork(object sender, DoWorkEventArgs e)
        {
            WLBSettings settings = e.Argument as WLBSettings;
            BackupMethods bMethods = new BackupMethods();
            // Begin backup by writing to logfile
            //WLBDebug.WriteToFile("Backup begun.");
            #region Check for cancel
            if (_doBackup.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            #endregion
            _doBackup.ReportProgress(12, "Backup started");
            bMethods.BackupSettings(settings);

            if (settings.Settings)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                _doBackup.ReportProgress(24, "Backing up Blog Settings...");
                WLBDebug.WriteToFile("Backing up Blog Settings...");
                bMethods.BackupBlogSettings();
                WLBDebug.WriteToFile("Finished backing up Blog Settings");
            }
            if (settings.IncludeBlogTemplates)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                WLBDebug.WriteToFile("Backing up Blog Templates...");
                _doBackup.ReportProgress(36, "Backing up Blog Templates...");
                bMethods.BackupBlogTemplates();
                WLBDebug.WriteToFile("Finished backing up Blog Templates");
            }
            if (settings.IncludeLinkGlossary)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                WLBDebug.WriteToFile("Backing up Link Glossary...");
                _doBackup.ReportProgress(48, "Backing up Link Glossary...");
                bMethods.BackupLinkGlossary();
                WLBDebug.WriteToFile("Finished backing up Link Glossary");
            }
            if (settings.Plugins)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                WLBDebug.WriteToFile("Backing up Plugins...");
                _doBackup.ReportProgress(60, "Backing up Plugins...");
                bMethods.BackupPlugins();
                WLBDebug.WriteToFile("Finished backing up Plugins");
            }
            if (settings.RecentPosts)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                WLBDebug.WriteToFile("Backing up Recent Posts...");
                _doBackup.ReportProgress(72, "Backing up Recent Posts (This may take a while)...");
                bMethods.BackupRecentPosts();
                WLBDebug.WriteToFile("Finished backing up Recent Posts");
            }
            if (settings.Drafts)
            {
                #region Check for cancel
                if (_doBackup.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                #endregion
                WLBDebug.WriteToFile("Backing up Drafts...");
                _doBackup.ReportProgress(84, "Backing up Drafts...");
                bMethods.BackupDrafts();
                WLBDebug.WriteToFile("Finished backing up Drafts");
            }

            #region Check for cancel
            if (_doBackup.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            #endregion
            WLBDebug.WriteToFile("Compressing backup.");
            _doBackup.ReportProgress(96, "Finalizing backup");
            ZipUtil.ZipFiles(_tempFolder, _fileName, string.Empty);

        }

        void _doBackup_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            string message = (string)e.UserState;
            prgBackupProgress.Value = (double)e.ProgressPercentage;
            txtbProgressUpdate.Text = message;
        }

        void _doBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                WLBDebug.WriteToFile(e.Error.Message);
                WLBDebug.WriteToFile(e.Error.ToString());
            }
            if (e.Cancelled)
            {
                WLBDebug.WriteToFile("Backup was cancelled by the user.");
            }
            else
            {
                if (File.Exists(_fileName))
                {
                    WLBDebug.WriteToFile("Backup was successful.");
                    WLBDebug.WriteToFile(_fileName + " successfully written to.");
                }
                else
                {
                    WLBDebug.WriteToFile(_fileName + " was not written.");
                }
            }
            prgBackupProgress.Value = 100;
            txtbProgressUpdate.Text = "Backup completed.";
            btnCancel.Content = "OK";
            btnCancel.ToolTip = "Click to close"; // Work Item #1734 http://www.codeplex.com/WLWBackup/WorkItem/View.aspx?WorkItemId=1734
            _isFinished = true;
        }
        #endregion

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (_isRestore || _isFinished)
            {
                BackupRestoreFinished();
            }
            else
            {
                _doBackup.CancelAsync();
                txtbProgressUpdate.Text = "Cancelling backup...";
            }
        }
	}
}